﻿using System;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Common;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SpriteGame.Rendering;
using System.Collections.Generic;
using FarseerPhysics.Common.Decomposition;
using SpriteGame.Helpers;

namespace SpriteGame
{
    public class ComplexShape:BaseSprite
    {
        public override Vector2 Position
        {
            get
            {
                //FarseerPhysics.DebugViewXNA.DebugViewXNA.Instance.DrawPoint(body.WorldCenter, 0.2f, Color.Red);
                return body.WorldCenter;
            }
            set
            {
                base.Position = value;
            }
        }

        List<Fixture> compound;

        public ComplexShape() { }

        public ComplexShape(Scene _parent, BodyType _type, Vector2 _position, float _rotation, String _texture)
        {

            //List<Fixture> fixtures = FixtureFactory.CreateCapsule(World, 3, 1, 1);
            //fixtures[0].Body.SetTransform(_position, _rotation);
            //fixtures[0].Body.BodyType = _type;

            BodyType = _type;
            StartPosition = _position;
            StartRot = _rotation;
            Texture = _texture;

            LoadContent(_parent);
            //FixtureFactory.CreateRoundedRectangle(World, 3, 3, 0.25F, 0.25F, 2, 1, new Vector2(-10, 10));
        }

        Vector2 offsetVector;
        Vector2 centroid;

        public override void LoadContent(Scene _parent)
        {
            parent = _parent;
            world = parent.World;

            texture = texture;

            List<Vertices> list;
            Vertices verts;

            Texture2D polygonTexture = TextureLibrary.GetTexture(texture);

            //body.
            width = polygonTexture.Width * 0.07f;
            height = polygonTexture.Height * 0.07f;

            list = GeometryPool.GetGeometry(texture);

            if (list == null)
            {
                uint[] data = new uint[polygonTexture.Width * polygonTexture.Height];

                polygonTexture.GetData(data);
                /*
                for (int y = 0; y < polygonTexture.Height / 2; y++)
                {
                    for (int x = 0; x < polygonTexture.Width; x++)
                    {
                        int y1 = y * polygonTexture.Width;
                        int y2 = ((polygonTexture.Height - 1) - y) * polygonTexture.Width;

                        uint a = data[y1];

                        data[y1] = data[y2];
                        data[y2] = a;
                    }    
                }*/
                //Find the vertices that makes up the outline of the shape in the texture
                verts = PolygonTools.CreatePolygon(data, polygonTexture.Width, polygonTexture.Height, true);

                Vector2 textureCentroid = new Vector2(polygonTexture.Width * 0.5f, polygonTexture.Height * 0.5f);
                verts.MirrorY(0.0f);
                Vector2 yTranslate = new Vector2(0, polygonTexture.Height);

                verts.Translate(ref yTranslate);
                Vector2 shapeCentroid = verts.GetCentroid();

                Vector2 centroidDiff = textureCentroid - shapeCentroid;

                //For now we need to scale the vertices (result is in pixels, we use meters)
                Vector2 scale = new Vector2(0.07f, 0.07f);

                verts.Scale(ref scale);
                Vector2 widthHeight = new Vector2(width, height);
                widthHeight *= 0.5f;

                //if (BodyType == FarseerPhysics.Dynamics.BodyType.Static)
                //    centroid = Vector2.Zero;
                //else
                //    centroid = -verts.GetCentroid();
                //Vector2 transform = centroid * -Vector2.UnitY * 0.5f;
                //verts.MirrorY(textureCentroid.Y * 0.07f);

                //Vector2 yDiff = (new Vector2(polygonTexture.Width * 0.5f, polygonTexture.Height * 0.5f) * 0.07f) - centroid;
                //centroid += (yDiff - centroid);

                //centroid += transform;
                //Vector2 flip = new Vector2(1, -1);
                //verts.Scale(ref flip);

                //Since it is a concave polygon, we need to partition it into several smaller convex polygons
                //list = BayazitDecomposer.ConvexPartition(verts);

                list = EarclipDecomposer.ConvexPartition(verts);
                GeometryPool.AddGeometry(texture, list);
            }

            //Create a single body with multiple fixtures
            compound = FixtureFactory.CreateCompundPolygon(World, list, 1);
  
            compound[0].Body.BodyType = BodyType;

            if (BodyType == FarseerPhysics.Dynamics.BodyType.Static)
                centroid = Vector2.Zero;
            else
                centroid = -compound[0].Body.LocalCenter;

            body = compound[0].Body;
            
            Vector2 posVec = ((StartPosition - offsetVector) - StartPosition) * 0.8f;
            body.SetTransform(StartPosition, 0.0f);

            body.UserData = this;

            isLoaded = true;
            //base.LoadContent(_parent);
        }

        public override void Draw(ShapeRenderer _batch)
        {
            //FarseerPhysics.DebugViewXNA.DebugViewXNA.Instance.DrawPoint(Position, 0.5f, Color.Orange);
            Vector2 posVec = ((Position - offsetVector) - Position) * 0.8f;

            //FarseerPhysics.DebugViewXNA.DebugViewXNA.Instance.DrawPoint(Position + (body.LocalCenter * 0.75f), 0.5f, Color.Green);

            //posVec *= -1f;
            //FarseerPhysics.DebugViewXNA.DebugViewXNA.Instance.DrawPoint(Position + posVec, 0.5f, Color.Red);
            //FarseerPhysics.DebugViewXNA.DebugViewXNA.Instance.DrawPoint(Position - offsetVector, 0.5f, Color.Blue);

            FarseerPhysics.DebugViewXNA.DebugViewXNA.Instance.DrawPoint(Position + centroid, 1.0f, Color.Red);

            Matrix transforms = 
            Matrix.CreateTranslation(centroid.X, centroid.Y, 0)*
            Matrix.CreateRotationZ(Rotation)*
            Matrix.CreateTranslation(Position.X, Position.Y, 0);

            _batch.DrawQuad(transforms, Width, Height, TextureLibrary.GetTexture(texture));

            //_batch.DrawQuad(Position, Rotation, width, height, TextureLibrary.GetTexture(texture)); 
        }
    }
}
